<html>
<script>

const curry = fn => (...argsFuck) => fn.bind(null, ...argsFuck);

const map = curry((fn, arr) => arr.map(fn));

function print(...arg){
  console.log("Jerry: " + arg);
}

var test = [1,2,3];

map(print, test)();

//var fn = function (a, b, c) {return a + b + c}; curryIt(fn)(1)(2)(3);
//输出例子:
/* 
题目描述
已知 fn 为一个预定义函数，实现函数 curryIt，调用之后满足如下条件：
1、返回一个函数 a，a 的 length 属性值为 1（即显式声明 a 接收一个参数）
2、调用 a 之后，返回一个函数 b, b 的 length 属性值为 1
3、调用 b 之后，返回一个函数 c, c 的 length 属性值为 1
4、调用 c 之后，返回的结果与调用 fn 的返回值一致
5、fn 的参数依次为函数 a, b, c 的调用参数 
输入例子:
var fn = function (a, b, c) {return a + b + c}; curryIt(fn)(1)(2)(3);
输出例子:
6
*/ 
let fn = function (a, b, c) {
  return a + b + c 
}; 

// JS中的柯里化(currying)（http://www.zhangxinxu.com/wordpress/2013/02/js-currying/）

// apply
function curryIt2(fn) {
    var arr = [];
    return function(a) {
        arr.push(a);
        return function(b) {
            arr.push(b);
            return function(c) {
                arr.push(c);
                return fn.apply(this, arr); // execution is delayed until (3)
            }
        }
    }
}

// 推荐写法
function curryIt3(fn) {
    return function(e1) {
        return function(e2) {
            return function(e3) {
                return fn(e1, e2, e3); // return fn.call(this, e1, e2, e3); 与之等价
            }
        }
    }
}
// 箭头函数
const curryIt4 = fn => e1 => e2 => e3 => fn(e1, e2, e3);

// 箭头函数
const curryIt5 = (fn) => { return ( e1 ) => { return  ( e2 ) =>  { return ( e3 )  => { return fn(e1, e2, e3) } } } };

console.log(curryIt2(fn)(1)(2)(3));
console.log(curryIt3(fn)(1)(2)(3));
console.log(curryIt4(fn)(1)(2)(3)); // e1, e2 is closure, e3 is local input variable
console.log("Jerry");
console.log(curryIt5(fn)(1)(2)(3));
</script>
</html>